#include "Display.h"
#include "Sprite.h"

//this is overkill. Sprite will take care of this.
void DrawGLCircle( const glm::vec2 & center, float rad, int numSecs )
{

	float steps = 6.29f / (float)(numSecs+1);
	glBegin(GL_TRIANGLE_FAN);
		glVertex2fv(&(center[0]));
		for (float i = 0; i <= 6.35; i += steps)
		{
			glm::vec2 tvec(std::sin((double)i)*rad, std::cos((double)i)*rad);
			glColor4f(i/6.35, 1.0 - (i/6.35), 0.5, 1.0);
			glVertex2f(center.x + tvec.x,
				center.y + tvec.y);
		}
	glEnd();
}


void DrawCircle( PhysicsPrimitive *inPrim)
{
	b2CircleShape * cs = (b2CircleShape*)inPrim->mFixture->GetShape();
	
	b2Vec2 pos = inPrim->GetPos();

	//Draw as a box for now.
	const b2Transform xf1 = inPrim->mBody->GetTransform();
	b2Vec2 cent = b2Mul(xf1, cs->m_p);
	glm::vec2 glcent;
	glcent.x = cent.x; glcent.y = cent.y;
	
	glm::vec2 line[2];
	b2Vec2 xax = xf1.q.GetXAxis(),
		yax = xf1.q.GetYAxis();
	line[0] = glm::vec2(xax.x, xax.y);
	line[1] = glm::vec2(yax.x, yax.y);

	//Draw Axis lines
	glBegin(GL_LINES);
	//X axis
		glVertex2f(glcent.x, glcent.y);
		glVertex2f(glcent.x + xax.x*(cs->m_radius*2),
			glcent.y + xax.y*(cs->m_radius*2));
	//Y axis
		glVertex2f(glcent.x, glcent.y);
		glVertex2f(glcent.x + yax.x*(cs->m_radius*2),
			glcent.y + yax.y*(cs->m_radius*2));
	glEnd();

	DrawGLCircle(glm::vec2(pos.x, pos.y), cs->m_radius, 10);

}

void DrawChain( PhysicsPrimitive * inPrim )
{
	b2ChainShape * cs = (b2ChainShape *)inPrim->mShape;

	if (inPrim->mShape->m_type != b2Shape::e_chain) {
		return;
	}
	unsigned int numV = cs->GetChildCount();
	if (numV < 1) {
		return;
	}

	const b2Transform xf1 = inPrim->mBody->GetTransform();
	b2EdgeShape edge;
	b2Vec2 pt[2];
	glBegin(GL_LINES);
	for (int i = 0; i < cs->GetChildCount(); ++i){
		cs->GetChildEdge(&edge, i);
		pt[0] = b2Mul(xf1, edge.m_vertex1);
		pt[1] = b2Mul(xf1, edge.m_vertex2);
		glVertex2f(pt[0].x, pt[0].y);
		glVertex2f(pt[1].x, pt[1].y);
		
	}
	glEnd();
}

void DrawPolygon(PhysicsPrimitive * inPrim)
{

	b2PolygonShape * poly = (b2PolygonShape*)inPrim->mFixture->GetShape();
        
    int32 vertexCount = poly->m_vertexCount;
        
 //   printf("Vertex count: %d\n", vertexCount);
       
    b2Assert(vertexCount <= b2_maxPolygonVertices);
                  
	const b2Transform xf1 = inPrim->mBody->GetTransform();
//    printf("transform: %f %f\n", xf1.p.x, xf1.p.y);
    b2Vec2 initv = b2Mul(xf1, poly->m_vertices[0]);
    b2Vec2 v1 = initv;
    b2Color col(1.0, 0.0, 0.0);
   	glBegin(GL_LINES);

	for (int32 i = 1; i < vertexCount; ++i)
    {
        b2Vec2 v2 = b2Mul(xf1, poly->m_vertices[i]);
		glVertex2f(v1.x, v1.y);
		glVertex2f(v2.x, v2.y);
        v1 = v2;
    }
        
    //Final segment:
	glVertex2f(v1.x, v1.y);
	glVertex2f(initv.x, initv.y);

	glEnd();
}

void DrawPhysicsPrimitive ( PhysicsPrimitive * inPrim )
{
	b2Fixture * fix = inPrim->mFixture;
	
	switch(fix->GetType())
	{
		case b2Shape::e_polygon:
			glColor3f(1.0, 0.0, 0.0);
			DrawPolygon(inPrim);
			break;
		case b2Shape::e_circle:
			glColor3f(0.0, 1.0, 0.0);
			DrawCircle(inPrim);
			break;
		case b2Shape::e_chain:
			glColor3f(0.0, 0.0, 1.0);
			DrawChain(inPrim);
			break;
		default:
			break;
	}
}

void DrawSprite (Sprite * inSprite, 
	const glm::vec2 & worldPos, 
	const glm::vec2 & worldWH,
	float angle = PI/2) {
	Texture * tex = inSprite->GetTexture();

	glm::vec2 uv, uvwh;

	uv = inSprite->GetUV();
	uvwh = inSprite->GetUVWH();

	//Sets to identity matrix.
	glPushMatrix();
	//glLoadIdentity();
	glTranslatef(worldPos.x, worldPos.y, 0);
	glRotatef(glm::degrees(angle), 0, 0, 1);

	glm::vec2 halfSpan; halfSpan.x = worldWH.x/2; halfSpan.y = worldWH.y/2;
	//XXX Fill this in
	//If tex is NULL, draw a white block
	if (tex == NULL) {
		glDisable(GL_TEXTURE_2D);		
		glColor4f(1.0, 0.0, 0.0, 1.0);
		glBegin(GL_QUADS); 
		glVertex2f(-halfSpan.x, halfSpan.y);
		glVertex2f(-halfSpan.x, -halfSpan.y);
		glVertex2f(halfSpan.x, -halfSpan.y);
		glVertex2f(halfSpan.x, halfSpan.y);
		glEnd();
	}
	else {
		glColor4f(1.0, 1.0, 1.0, 1.0);
		glEnable( GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D, tex->mTexName);
		glBegin(GL_QUADS); 
			glTexCoord2f(uv.x, uv.y);
		glVertex2f(-halfSpan.x, halfSpan.y);
			
			glTexCoord2f(uv.x + uvwh.x, uv.y);
		glVertex2f(-halfSpan.x, -halfSpan.y);
			
			glTexCoord2f(uv.x + uvwh.x, uv.y + uvwh.y);
		glVertex2f(halfSpan.x, -halfSpan.y);
		
			glTexCoord2f(uv.x, uv.y + uvwh.y);
		glVertex2f(halfSpan.x, halfSpan.y);
		glEnd();
		glDisable(GL_TEXTURE_2D);
	}

	glPopMatrix();
}

void DrawCrossHair(float x, float y) {
	glColor3f(1.0, 0.0, 0.0);
	glPointSize(5.0);
	glBegin(GL_POINTS);
	glVertex2f(x, y);
	glEnd();
}